package com.strato.rpc.hessian.v1_0_0.ha;

import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;

import com.strato.rpc.hessian.v1_0_0.HessianHttpTransport;

public class RoundRobinHAStrategy extends AbstractHAStrategy {

	private static long checkInterval=30*1000;
			
	public RoundRobinHAStrategy(String path, Class<?> intf, HessianHttpTransport transport) {
		super(path, intf, transport);
	}

	private Iterator<Map.Entry<String,Object>> proxyIter=null;
	
	@Override
	public String nextProxyId() {
		synchronized(this){
			Map<String, Object> proxies = getProxies();
			for(int i=0,len=proxies.size();i<len;i++){
				if(proxyIter==null||!proxyIter.hasNext()){
					proxyIter=proxies.entrySet().iterator();
				}
				Entry<String, Object> entry = proxyIter.next();
				String baseurl=entry.getKey();
				InvocationStatics stat = getStat(baseurl);
				if(stat.isAvailable()){
					logger.debug("Next Proxy ID:"+baseurl);
					return baseurl;
				}else{
					Long lastfall = stat.getLastFall();
					if(lastfall==null||System.currentTimeMillis()-lastfall>checkInterval){
						StringBuffer msg=new StringBuffer("Try connect "+baseurl);
						if(tryConnect(baseurl)){
							msg.append("...connected.");
							logger.info(msg.toString());
							stat.markAvailable();
							return baseurl;
						}
						msg.append("...disconnected.Target is down!");
						logger.warn(msg.toString());
						stat.markUnavailable();
					}
				}
			}
		}
		throw new IllegalStateException("All RPC targets are down!!!");
	}

	private static boolean tryConnect(String baseurl) {
		try {
			URL url=new URL(baseurl);
			HttpURLConnection conn=(HttpURLConnection) url.openConnection();
			conn.setConnectTimeout(500);
			conn.connect();
			conn.disconnect();
			return true;
		} catch (MalformedURLException e) {
			return false;
		} catch (IOException e) {
			return false;
		}
	}
}
